package com.adopapa.wechatapi.application.service;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Calendar;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;

import com.adopapa.wechatapi.domain.common.ResultMessage;
import com.adopapa.wechatapi.domain.event.WeChatEvent;
import com.adopapa.wechatapi.domain.media.DownloadMediaResult;
import com.adopapa.wechatapi.domain.media.UploadMediaResult;
import com.adopapa.wechatapi.domain.media.UploadMediaResult.MediaType;
import com.adopapa.wechatapi.domain.message.ImageRequestMessage;
import com.adopapa.wechatapi.domain.message.LinkRequestMessage;
import com.adopapa.wechatapi.domain.message.LocationRequestMessage;
import com.adopapa.wechatapi.domain.message.RequestMessage;
import com.adopapa.wechatapi.domain.message.RequestMessage.MessageType;
import com.adopapa.wechatapi.domain.message.ResponseMessage;
import com.adopapa.wechatapi.domain.message.TextRequestMessage;
import com.adopapa.wechatapi.domain.message.TextResponseMessage;
import com.adopapa.wechatapi.domain.message.VideoRequestMessage;
import com.adopapa.wechatapi.domain.message.VoiceRequestMessage;
import com.adopapa.wechatapi.domain.message.customer.CustomerServiceMessage;
import com.adopapa.wechatapi.util.MessageUtil;
import com.adopapa.wechatapi.xstream.XstreamUtil;
import com.qq.weixin.mp.aes.WXBizMsgCrypt;

public class WeChatService {

	private final Logger logger = Logger.getLogger(WeChatService.class);

	/**
	 * 被动回复消息
	 * 
	 * @throws IOException
	 */
	public static void sendResponseMessage(ResponseMessage responseMessage, HttpServletResponse response)
			throws IOException {
		PrintWriter out = response.getWriter();
		out.print(responseMessage.toXml());
		out.close();
	}

	

	/**
	 * 不加密处理来自微信服务器的请求
	 */
	public void process(HttpServletRequest request, HttpServletResponse response) throws Exception {
		logger.info("不加密处理来自微信服务器的请求");
		InputStream inputStream = request.getInputStream();
		byte[] bytes = readStream(inputStream);
		Map<String, String> requestMap = MessageUtil.parseXml(new ByteArrayInputStream(bytes));
		String msgType = requestMap.get("MsgType");
		logger.info(requestMap);
		RequestMessage requestMessage = null;
		if (MessageType.image.name().equalsIgnoreCase(msgType)) {
			requestMessage = new ImageRequestMessage();
			requestMessage.fromMap(requestMap);
			processMessage(requestMessage, request, response);
		} else if (MessageType.link.name().equalsIgnoreCase(msgType)) {
			requestMessage = new LinkRequestMessage();
			requestMessage.fromMap(requestMap);
			processMessage(requestMessage, request, response);
		} else if (MessageType.location.name().equalsIgnoreCase(msgType)) {
			requestMessage = new LocationRequestMessage();
			requestMessage.fromMap(requestMap);
			processMessage(requestMessage, request, response);
		} else if (MessageType.text.name().equalsIgnoreCase(msgType)) {
			requestMessage = new TextRequestMessage();
			requestMessage.fromMap(requestMap);
			processMessage(requestMessage, request, response);
		} else if (MessageType.video.name().equalsIgnoreCase(msgType)) {
			requestMessage = new VideoRequestMessage();
			requestMessage.fromMap(requestMap);
			processMessage(requestMessage, request, response);
		} else if (MessageType.voice.name().equalsIgnoreCase(msgType)) {
			requestMessage = new VoiceRequestMessage();
			requestMessage.fromMap(requestMap);
			processMessage(requestMessage, request, response);
		} else if (MessageType.event.name().equalsIgnoreCase(msgType)) {
			logger.info("process wechat event");
			WeChatEvent weChatEvent = XstreamUtil.XML2Bean(new ByteArrayInputStream(bytes), WeChatEvent.class);
			processEvent(weChatEvent, request, response);
		}

	}

	/**
	 * 处理接受事件推送
	 */
	public void processEvent(WeChatEvent weChatEvent, HttpServletRequest request, HttpServletResponse response)
			throws Exception {

	}

	/**
	 * 处理接受消息
	 */
	public void processMessage(RequestMessage requestMessage, HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		TextResponseMessage responseMessage = new TextResponseMessage();
		responseMessage.setCreateTime(Calendar.getInstance().getTime().getTime());
		responseMessage.setFromUserName(requestMessage.getToUserName());
		responseMessage.setToUserName(requestMessage.getFromUserName());
		responseMessage.setContent("您的反馈已经记录, 谢谢您的支持!");
		sendResponseMessage(responseMessage, response);
	}

	public ResultMessage sendCustomerServiceMessage(CustomerServiceMessage customerServiceMessage, String accessToken)
			throws Exception {
		return WeChatApi.sendCustomerServiceMessage(customerServiceMessage, accessToken);
	}

	/**
	 * 把输入流中数据读取到字节数据中
	 */
	private static byte[] readStream(InputStream inputStream) throws Exception {
		ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = -1;
		while ((len = inputStream.read(buffer)) != -1) {
			outSteam.write(buffer, 0, len);
		}
		outSteam.close();
		inputStream.close();
		return outSteam.toByteArray();
	}

	public UploadMediaResult uploadMedia(String accessToken, File file, MediaType mediaType) throws Exception {
		if (!mediaType.checkSizeLimit(file)) {
			// 40009 不合法的图片文件大小
			// 40010 不合法的语音文件大小
			// 40011 不合法的视频文件大小
			// 40012 不合法的缩略图文件大小
			if (mediaType == MediaType.image) {
				return new UploadMediaResult(40009, "不合法的图片文件大小");
			} else if (mediaType == MediaType.voice) {
				return new UploadMediaResult(40010, "不合法的语音文件大小");
			} else if (mediaType == MediaType.video) {
				return new UploadMediaResult(40011, "不合法的视频文件大小");
			} else if (mediaType == MediaType.thumb) {
				return new UploadMediaResult(40012, "不合法的缩略图文件大小");
			}
		}

		return WeChatApi.uploadMedia(accessToken, file, mediaType.name());
	}

	public DownloadMediaResult downloadMedia(String accessToken, String mediaId) throws Exception {
		return WeChatApi.downMedia(accessToken, mediaId);
	}

}
